(function () {
    var Turret = (function (_super) {
        function Turret(data) {
            Turret.super(this);

            this.turret = null;
            this.direction = null;
            this.tips = null;
            this.timeline = null;
            
            this.create(data);
        }
        Laya.class(Turret, "", _super);
        var _proto = Turret.prototype;
        _proto.destroy = function () {
            _super.prototype.destroy.call(this, true);

            this.turret = null;
            this.direction = null;
            this.tips = null;
            this.timeline = null;
        }

        _proto.create = function (data) {
            var tips = new Laya.Image("res/game/map/turret_tip.png");
                tips.pivot(28, 70);
                tips.pos(0, -100);

            var timeline = new Laya.TimeLine();
                timeline.to(tips, {scaleX : 0.9, y : -90}, 300)
                        .to(tips, {scaleX : 1.1, y : -110}, 300)
                        .to(tips, {scaleX : 1, y : -100}, 300);

                timeline.play(0, true);

            this.timeline = timeline;
            this.direction = data.direction;
            this.tips = tips;
            this.turret = utils.createSkeleton("other/special/turret");
            this.addChildren(this.turret, tips);

            this.wait();

            Laya.timer.once(3000, this, function () {
                this.timeline.destroy(true);
                this.tips.destroy(true);
            });
        }
        _proto.wait = function () {
            console.log("turret direction:" + this.direction);
            this.turret.play("wait_" + this.direction, true);
        }
        _proto.attack = function () {
            this.turret.play("fire_" + this.direction, false);
            this.turret.on(Laya.Event.STOPPED, this, function () {
                this.wait()
            });
        }
        return Turret;
    })(Laya.Sprite);
    
    var TileTexture = (function (_super) {
        /**
         * 地图的每层都会分块渲染处理
         * 本类就是地图的块数据
         */
        function TileTexture(tex, itemData) {
            this._texture = null;
            this._clips = [];
            this._clipX = 1;
            this._clipY = 1;
            this._clipWidth = 0;
            this._clipHeight = 0;
            this._autoPlay = false;
            this._interval = 50;
            this._isPlaying = false;
            this._index = 0;
            this._data = null;

            TileTexture.super(this);
            this._init(tex, itemData);
        }
        Laya.class(TileTexture, "", _super);
        var _proto = TileTexture.prototype;
        _proto.destroy = function () {
            _super.prototype.destroy.call(this, true);

            this._texture = null;
            this._clips = null;
            this._clipX = null;
            this._clipY = null;
            this._clipWidth = null;
            this._clipHeight = null;
            this._autoPlay = null;
            this._interval = null;
            this._isPlaying = null;
            this._index = null;
            this._data = null;
        }

        _proto._drawTexture = function (tex) {
            this.graphics.clear();
            this.graphics.drawTexture(tex, 0, 0, this._clipWidth, this._clipHeight);        
        }
        _proto._loop = function () {
            this._index >= this._clips.length && (this._index = 0);
            this._drawTexture(this._clips[this._index]);
            this._index ++;
        }
        _proto._init = function (tex, itemData) {
            var clipX = this._clipX;
            var clipY = this._clipY;
            
            this.name = itemData.itemName;
            this.itemId = itemData.itemId;

            this.size(itemData.size.w, itemData.size.h)
            this.pivot(itemData.size.w / 2, itemData.size.h);

            if(itemData.animation){
                this._interval = itemData.animation.interval;

                this._clipX = itemData.animation.clipX;
                this._clipY = itemData.animation.clipY;

                this._clipWidth  = Math.ceil(tex.sourceWidth / this._clipX);
                this._clipHeight = Math.ceil(tex.sourceHeight / this._clipY);

                for(var i = 0; i < this._clipY; i ++){
                    for(var j =0; j < this._clipX; j ++){
                        this._clips.push(Laya.Texture.createFromTexture(tex, this._clipWidth * j, this._clipHeight * i, this._clipWidth, this._clipHeight));
                    }
                }
                Laya.timer.loop(this._interval, this, this._loop);
            }else{
                this._drawTexture(tex);
            }
        }

        /**
         * @public
         * 销毁地图元件
         */
        _proto.destroy = function () {
            Laya.Sprite.prototype.destroy.call(this, true);

            this._texture = null;
            this._clips = [];
        }

        return TileTexture;
    })(Laya.Sprite);

    (function (_super) {
        /**
         * TiledMap是整个地图的核心
         * 地图以层级来划分地图（例如：地表层，建筑层）
         * 每层又以分块（TileTexture)来处理显示对象
         * 每块又包括N*N个格子（tile)
         * 格子类型又分为动画格子跟图片格子两种
         */
        function TiledMap() {
            TiledMap.super(this);

            this._tileWidth = 0;
            this._tileHeight = 0;
            this._row = 0;
            this._col = 0;
            this._resPath = null;
            this._atlas = null;
            this._jsonData = null;
            this._items = {};
            this._floorData = [];
            this._buildingsData = [];
            this._textures = [];
            this._buildings = {};
            this._floor = null;
            this._wrap = null;

            this._smoke = null;
        }
        Laya.class(TiledMap, "Game.TiledMap", _super);

        var _proto = TiledMap.prototype;
        /**
         * @public
         * 销毁地图
         */
        _proto.destroy = function () {
            _super.prototype.destroy(this, true);

            this._tileWidth = null;
            this._tileHeight = null;
            this._row = null;
            this._col = null;
            this._resPath = null;
            this._atlas = null;
            this._jsonData = null;
            this._items = null;
            this._floorData = null;
            this._buildingsData = null;
            this._textures = null;
            this._buildings = null;
            this._floor = null;
            this._wrap = null;
            this._smoke = null;
        }

        _proto._parseData = function (mapData) {
            var meta  = mapData.meta;
            var items = mapData.items;
            var layer = mapData.layer;

            for(var i in items){
                var item = items[i];
                this._items[item.itemId] = item;
            }

            this._tileWidth  = meta.tileSize.w;
            this._tileHeight = meta.tileSize.h;
            this._row = meta.size.h;
            this._col = meta.size.w;

            this._floorData     = layer.floor;
            this._buildingsData = layer.buildings;

            this.name   = meta.name;
            this.width  = meta.size.w * meta.tileSize.w;
            this.height = meta.size.h * meta.tileSize.h;
        }
        _proto._createTexture = function (atlas) {
            var items = this._items;
            var tex   = this._textures;

            for(var i in items){
                var item = items[i];
                tex[i] = Laya.Texture.create(atlas, item.frame.x, item.frame.y, item.frame.w, item.frame.h);
            }
        }
        _proto._createFloor = function () {
            var tex   = this._textures;
            var items = this._items;
            var row   = this._row;
            var col   = this._col;
            var fd    = this._floorData;
            var tw    = this._tileWidth;
            var th    = this._tileHeight;
            var floor = new Laya.Sprite();

            for(var i = 0; i < row; i++){
                for(var j = 0; j < col; j++){
                    var _sprite = new TileTexture(tex[fd[i][j]], items[fd[i][j]]);
                        //_sprite.graphics.drawTexture(tex[fd[i][j]], 0, 0, 80, 76);
                        _sprite.pos(j * tw + items[fd[i][j]].offset.x + (items[fd[i][j]].size.w / 2), i * th + items[fd[i][j]].offset.y + th);
                    floor.addChild(_sprite);
                }
            }
            floor.cacheAs = "bitmap";
            floor.staticCache = true;
            this._floor = floor;

            this.addChild(floor);
        }
        _proto._createBuildings = function () {
            var tex   = this._textures;
            var items = this._items;
            var row   = this._row;
            var col   = this._col;
            var bd    = this._buildingsData;
            var tw    = this._tileWidth;
            var th    = this._tileHeight;
            var wrap  = new Laya.Sprite();

            for(var i = 0; i < row; i++){
                for(var j = 0; j < col; j++){
                    if(bd[i][j] == 0){continue;}
                    var _sprite = new TileTexture(tex[bd[i][j]], items[bd[i][j]]);
                        _sprite.alpha = 0;
                        _sprite.name = "B_" + j + ":" + i;
                        _sprite.realPosY = i * th + items[bd[i][j]].offset.y + th;
                        _sprite.pos(j * tw + items[bd[i][j]].offset.x + (items[bd[i][j]].size.w / 2), _sprite.realPosY - 30);
                        _sprite.zOrder = (i + 1) * th;
                    wrap.addChild(_sprite);
                    if(items[bd[i][j]].length != 1){
                        j += (items[bd[i][j]].length - 1);
                    }
                }
            }
            this._wrap = wrap;

            this.addChild(wrap);
        }
        _proto._createTurret = function () {
            var tw = this._tileWidth;
            var th = this._tileHeight;
            var turretData = this._jsonData.config.turret;
            if(turretData){
                for(var i in turretData){
                    var _turretData = turretData[i];
                    var _turret = new Turret(_turretData);
                        _turret.name = "T_" + _turretData.x + ":" + _turretData.y;
                        _turret.pos(_turretData.x * tw + tw / 2, _turretData.y * th + th);

                    this.add(_turret);
                }
            }
        }

        _proto.attack = function (x, y) {
            var turret = this._wrap.getChildByName("T_" + x + ":" + y);

            turret && turret.attack();
        }
        /**
         * @public
         * 删除指定索引的建筑物
         * @param {Point} x,y 建筑物的索引值
         */
        _proto.remove = function (x, y) {
            var building = this._wrap.getChildByName("B_" + x + ":" + y);
            if(!building){return;}

            building.destroy();

            var smoke = new Laya.Clip("res/game/map/smoke.png", 6, 1);
                smoke.anchorX = 0.5;
                smoke.anchorY = 1;
                smoke.interval = 100;
                smoke.x = building.x; 
                smoke.y = building.y;
                smoke.on(Laya.Event.CHANGE, smoke, function (building) {
                    if(this.index === this.total - 1){
                        this.stop();
                        Laya.timer.once(100, this, function () {
                            this.destroy();
                        });
                    }
                });

            this._wrap.addChild(smoke);
            smoke.play();
        }
        /**
         * @public
         * 删除指定索引的建筑物
         * @param {Point} x,y 建筑物的索引值
         */
        _proto.move = function (point, direction) {
            var move = {x : 0, y : 0};
            var building = this._wrap.getChildByName("B_" + point.x + ":" + point.y);
            if(!building){return;}

            switch(direction){
                case "up":
                    move.x = 0;
                    move.y = -1;
                    break;
                case "down":
                    move.x = 0;
                    move.y = 1;
                    break;
                case "left":
                    move.x = -1;
                    move.y = 0;
                    break;
                case "right":
                    move.x = 1;
                    move.y = 0;
                    break;
            }
            building.name = "B_" + (point.x + move.x) + ":" + (point.y + move.y);
            
            // building.x = (point.x + move.x) * 72 + 36;
            // building.y = (point.y + 1 + move.y) * 72;

            building.zOrder = (point.y + 1 + move.y) * 72;
            Laya.Tween.to(building, {x : (point.x + move.x) * 72 + 36, y : (point.y + 1 + move.y) * 72}, 500, Laya.Ease.backOut);
        }
        /**
         * @public
         * 添加角色、物件到建筑层
         * @param {Game.Role | Game.Bubble | Game.Prop} object 游戏角色、泡泡、道具
         */
        _proto.add = function (object) {
            object.zOrder = object.y;
            this._wrap.addChild(object);
        }
        /**
         * @public
         * 创建地图
         * @param {String} path 地图路径
         */
        _proto.create = function (path) {
            var mapData = Laya.loader.getRes(path + "/map.json");
            var atlas   = Laya.loader.getRes(path + "/texture.png").bitmap;
            
            if (Laya.Render.isWebGL){
                atlas.minFifter=0x2600;
                atlas.magFifter=0x2600;
                atlas.enableMerageInAtlas=false;
            }

            this._resPath  = path;
            this._jsonData = mapData;

            this._parseData(mapData);
            this._createTexture(atlas);
            this._createFloor();
            this._createBuildings();
            //this._createTurret();
        }

        _proto.enter = function (callback) {
            var row   = this._row;
            var col   = this._col;
            var buildWrap = this._wrap;
            var delay = 0;

            for(var i = 0; i < row; i++){
                for(var j = 0; j < col; j++){
                    var build = buildWrap.getChildByName("B_" + j + ":" + i);
                    if(build){
                        delay += 20;
                        Laya.Tween.to(build, {y : build.realPosY, alpha : 1}, 500, Laya.Ease.backOut, null, delay);
                    }
                }
            }
            Laya.timer.once(delay + 50, this, this._createTurret);
            Laya.timer.once(delay + 100, this, callback);
        }
    })(Laya.Component);

})();